home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 1 / ETO Development Tools 1.iso / Tools - Objects / MacApp / MacApp 2.0 CD Release / MacApp 2.0 (Many Libraries) / Examples / DrawShapes / UMenu.inc1.p < prev    next >
Encoding:
Text File  |  1990-03-27  |  14.3 KB  |  649 lines  |  [TEXT/MPS ]

  1. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  2.  
  3. TYPE
  4.     MenuRec             = RECORD
  5.         mID:                INTEGER;
  6.         mObject:            TMenu;
  7.         END;
  8.     MenuArray            = ARRAY [1..4000] OF MenuRec;
  9.     MenuArrayPtr        = ^MenuArray;
  10.     MenuArrayHandle     = ^MenuArrayPtr;
  11.  
  12. VAR
  13.     pMenuCPort:         CGrafPort;                        { Color port for compatibility. }
  14.                                                         { Private grafPort used to focus the menu w/o
  15.                                                          messing up the Window Manager port. }
  16.     pMenuArray:         MenuArrayHandle;                { Used to find the TMenu given a MenuHandle.
  17.                                                          }
  18.     pNumMenus:            INTEGER;
  19.  
  20.     pCustDefproc:        Handle;                         { Replaces the menu's menuProc field }
  21.  
  22. {--------------------------------------------------------------------------------------------------}
  23.     { Returns the TickCount some time in the future. }
  24.  
  25. FUNCTION Future(delta: LONGINT): LONGINT;
  26.  
  27.     BEGIN
  28.     Future := TickCount + delta;
  29.     END;
  30.  
  31. {--------------------------------------------------------------------------------------------------}
  32.  
  33. {$S ARes}
  34.  
  35. PROCEDURE WaitTickChange;
  36.  
  37.     VAR
  38.         now:                LONGINT;
  39.  
  40.     BEGIN
  41.     now := TickCount;
  42.     REPEAT
  43.     UNTIL TickCount <> now;
  44.     END;
  45.  
  46. {--------------------------------------------------------------------------------------------------}
  47.  
  48. {$S ARes}
  49.  
  50. FUNCTION FindTMenu(theMenu: MenuHandle): TMenu;
  51.  
  52.     VAR
  53.         i:                    INTEGER;
  54.         p:                    MenuArrayPtr;
  55.         id:                 INTEGER;
  56.  
  57.     BEGIN
  58.     FindTMenu := NIL;
  59.     p := pMenuArray^;
  60.     id := theMenu^^.menuID;
  61.  
  62.     FOR i := 1 TO pNumMenus DO
  63.         WITH p^[i] DO
  64.             IF mID = id THEN
  65.                 BEGIN
  66.                 FindTMenu := mObject;
  67.                 Exit(FindTMenu);
  68.                 END;
  69.     END;
  70.  
  71. {--------------------------------------------------------------------------------------------------}
  72. { Called by the MDEF resource. }
  73.  
  74. {$S ARes}
  75.  
  76. PROCEDURE MenuDefproc(message: INTEGER;
  77.                       theMenu: MenuHandle;
  78.                       VAR menuRect: Rect;
  79.                       hitPt: Point;
  80.                       VAR whichItem: INTEGER);
  81.  
  82.     VAR
  83.         menuObj:            TMenu;
  84.  
  85.     BEGIN
  86.     menuObj := FindTMenu(theMenu);
  87.     {$IFC qDebug}
  88.     IF menuObj = NIL THEN
  89.         ProgramBreak('MenuDefproc called with no TMenu object');
  90.     {$ENDC}
  91.  
  92.     { Dispatch to the TMenu object }
  93.     menuObj.HandleDefproc(message, theMenu, menuRect, hitPt, whichItem);
  94.     END;
  95.  
  96. {--------------------------------------------------------------------------------------------------}
  97. {$S AInit}
  98.  
  99. PROCEDURE InitUMenu;
  100.  
  101.     TYPE
  102.         JMP                 = RECORD
  103.             opcode:             INTEGER;
  104.             address:            Ptr;
  105.             END;
  106.         JmpPtr                = ^JMP;
  107.         JmpHandle            = ^JmpPtr;
  108.  
  109.     VAR
  110.         h:                    JmpHandle;
  111.  
  112.     BEGIN
  113.     IF qNeedsColorQD | gConfiguration.hasColorQD THEN
  114.         OpenCPort(@pMenuCPort)
  115.     ELSE
  116.         OpenPort(GrafPtr(@pMenuCPort));
  117.     pNumMenus := 0;
  118.     pMenuArray := MenuArrayHandle(NewHandle(0));
  119.     FailNIL(pMenuArray);
  120.  
  121.     h := JmpHandle(NewHandle(6));
  122.     FailNIL(h);
  123.     WITH h^^ DO
  124.         BEGIN
  125.         opcode := $4EF9;
  126.         address := @MenuDefproc;
  127.         END;
  128.     pCustDefproc := Handle(h);
  129.     END;
  130.  
  131. {--------------------------------------------------------------------------------------------------}
  132. {$S AInit}
  133.  
  134. PROCEDURE TMenu.IMenu(rsrcID: INTEGER;
  135.                       menuWidth, menuHeight: INTEGER);
  136.  
  137.     VAR
  138.         m:                    MenuHandle;
  139.         s:                    LONGINT;
  140.         p:                    LongintPtr;
  141.         i:                    INTEGER;
  142.  
  143.         r:                    Rect;
  144.         item:                INTEGER;
  145.         vp:                 VPoint;
  146.  
  147.     BEGIN
  148.     { Initialize fields }
  149.     fBorder := gZeroRect;
  150.     fMenuHandle := NIL;
  151.     vp.h := menuWidth;
  152.     vp.v := menuHeight;
  153.     IView(NIL, NIL, gZeroVPt, vp, SizeVariable, SizeVariable);
  154.  
  155.     fFlashInterval := - 1;
  156.     fNextFlash := 0;
  157.  
  158.     IF rsrcID = 0 THEN
  159.         fMenuHandle := NIL
  160.     ELSE
  161.         BEGIN
  162.         { Read in menu and set its defproc }
  163.         m := MenuHandle(GetResMenu(rsrcID));
  164.  
  165.         IF m = NIL THEN
  166.             BEGIN
  167.             {$IFC qDebug}
  168.             Writeln('rsrcID = ', rsrcID: 1);
  169.             ProgramBreak('No such MENU!');
  170.             {$ENDC}
  171.  
  172.             Free;
  173.             Failure(resNotFound, 0);
  174.             END;
  175.  
  176.         pNumMenus := pNumMenus + 1;
  177.         SetHandleSize(Handle(pMenuArray), SIZEOF(MenuRec) * pNumMenus);
  178.         WITH pMenuArray^^[pNumMenus] DO
  179.             BEGIN
  180.             mID := m^^.menuID;
  181.             mObject := SELF;
  182.             END;
  183.  
  184.         m^^.menuProc := pCustDefproc;
  185.         fMenuHandle := m;
  186.  
  187.         MenuDefproc(mSizeMsg, m, r, Point(0), item);    { recompute the menu size }
  188.         END;
  189.     END;
  190.  
  191. {--------------------------------------------------------------------------------------------------}
  192. {$S MenuNever}
  193.  
  194. FUNCTION TMenu.FindItem(hitPt: Point): INTEGER;
  195.  
  196.     BEGIN
  197.     {$IFC qDebug}
  198.     ProgramBreak('You must override TMenu.FindItem.');
  199.     {$ENDC}
  200.     END;
  201.  
  202. {--------------------------------------------------------------------------------------------------}
  203. {$S ARes}
  204.  
  205. PROCEDURE TMenu.HandleDefproc(message: INTEGER;
  206.                               theMenu: MenuHandle;
  207.                               VAR menuRect: Rect;
  208.                               hitPt: Point;
  209.                               VAR whichItem: INTEGER);
  210.  
  211.     VAR
  212.         p:                    LongintPtr;
  213.         savePort:            GrafPtr;
  214.         r:                    Rect;
  215.  
  216.     BEGIN
  217.     { Save the wmgr port & set our private port }
  218.     GetPort(savePort);
  219.  
  220.     fMenuRect := menuRect;
  221.     fHitPt := hitPt;
  222.  
  223.     IF Focus THEN
  224.         BEGIN
  225.         hitPt := fHitPt;
  226.  
  227.         ViewEnable(Odd(fMenuHandle^^.enableFlags), false {no redraw} );
  228.         CASE message OF
  229.             mDrawMsg:
  230.                 BEGIN
  231.                 {$IFC qDebug}
  232.                 IF gIntenseDebugging THEN
  233.                     Writeln('mDrawMsg');
  234.                 {$ENDC}
  235.                 HandleDrawMessage(message, theMenu, menuRect, hitPt, whichItem);
  236.                 END;
  237.  
  238.             mChooseMsg:
  239.                 BEGIN
  240.                 {$IFC qDebug}
  241.                 IF gIntenseDebugging THEN
  242.                     Writeln('mChooseMsg');
  243.                 {$ENDC}
  244.                 HandleChooseMessage(message, theMenu, menuRect, hitPt, whichItem);
  245.                 END;
  246.  
  247.             mSizeMsg:
  248.                 BEGIN
  249.                 {$IFC qDebug}
  250.                 IF gIntenseDebugging THEN
  251.                     Writeln('mSizeMsg');
  252.                 {$ENDC}
  253.                 HandleSizeMessage(message, theMenu, menuRect, hitPt, whichItem);
  254.                 END;
  255.  
  256.             mPopUpMsg:
  257.                 BEGIN
  258.                 {$IFC qDebug}
  259.                 IF gIntenseDebugging THEN
  260.                     Writeln('mPopUpMsg');
  261.                 {$ENDC}
  262.                 HandlePopUpMessage(message, theMenu, menuRect, hitPt, whichItem);
  263.                 END;
  264.             {$IFC qDebug}
  265.             OTHERWISE
  266.                 IF gIntenseDebugging THEN
  267.                     Writeln('otherwise message');
  268.             {$ENDC}
  269.         END;
  270.         InvalidateFocus;
  271.         END;
  272.  
  273.     SetPort(savePort);
  274.     END;
  275.  
  276. {--------------------------------------------------------------------------------------------------}
  277. {$S ARes}
  278.  
  279. PROCEDURE TMenu.HandleChooseMessage(message: INTEGER;
  280.                                     theMenu: MenuHandle;
  281.                                     VAR menuRect: Rect;
  282.                                     hitPt: Point;
  283.                                     VAR whichItem: INTEGER);
  284.  
  285.     VAR
  286.         newItem:            INTEGER;
  287.         hitRect:            Rect;
  288.  
  289.     BEGIN
  290.     newItem := kNoMenuItem;                             { default return }
  291.  
  292.     { See what item the user is over }
  293.  
  294.     IF IsViewEnabled THEN                                { menu enabled }
  295.         BEGIN
  296.         { see if point is within hit area }
  297.         GetQDExtent(hitRect);
  298.         AddPt(fBorder.topLeft, hitRect.topLeft);
  299.         AddPt(fBorder.botRight, hitRect.botRight);
  300.  
  301.         IF PtInRect(hitPt, hitRect) THEN                { in menu (not border) }
  302.             newItem := FindItem(hitPt);
  303.         END;
  304.  
  305.     { Update highlighting }
  306.     UpdateHighlight(whichItem, newItem);
  307.  
  308.     { Tell MenuManager about new item }
  309.     whichItem := newItem;
  310.     END;
  311.  
  312. {--------------------------------------------------------------------------------------------------}
  313. {$S ARes}
  314.  
  315. PROCEDURE TMenu.HandleDrawMessage(message: INTEGER;
  316.                                   theMenu: MenuHandle;
  317.                                   VAR menuRect: Rect;
  318.                                   hitPt: Point;
  319.                                   VAR whichItem: INTEGER);
  320.     var
  321.         extent: Rect;
  322.  
  323.     BEGIN
  324.     DrawContents;
  325.     fHighlighted := false;
  326.     if not fViewEnabled THEN
  327.         begin
  328.         PenPat(Gray);
  329.         PenMode(notSrcBic);
  330.         GetQDExtent(extent);
  331.         PaintRect(extent);
  332.         end;
  333.     END;
  334.  
  335. {--------------------------------------------------------------------------------------------------}
  336. {$S ARes}
  337.  
  338. PROCEDURE TMenu.HandleSizeMessage(message: INTEGER;
  339.                                   theMenu: MenuHandle;
  340.                                   VAR menuRect: Rect;
  341.                                   hitPt: Point;
  342.                                   VAR whichItem: INTEGER);
  343.  
  344.     VAR
  345.         vp:                 VPoint;
  346.  
  347.     BEGIN
  348.     ComputeSize(vp);
  349.     fMenuHandle^^.menuWidth := vp.h;
  350.     fMenuHandle^^.menuHeight := vp.v;
  351.     END;
  352.  
  353. {--------------------------------------------------------------------------------------------------}
  354. {$S ARes}
  355.  
  356. PROCEDURE TMenu.HandlePopUpMessage(message: INTEGER;
  357.                                    theMenu: MenuHandle;
  358.                                    VAR menuRect: Rect;
  359.                                    hitPt: Point;
  360.                                    VAR whichItem: INTEGER);
  361.  
  362.     VAR
  363.         vp:                 VPoint;
  364.  
  365.     BEGIN
  366.     {  SubPt(origin, hitPt);}
  367.  
  368.     menuRect.top := hitPt.h;
  369.     menuRect.left := hitPt.v;
  370.     ComputeSize(vp);
  371.     menuRect.bottom := menuRect.top + vp.v;
  372.     menuRect.right := menuRect.left + vp.h;
  373.     END;
  374.  
  375. {--------------------------------------------------------------------------------------------------}
  376. {$S ARes}
  377.  
  378. PROCEDURE TMenu.Highlight(whichItem: INTEGER;
  379.                           turnItOn: BOOLEAN);
  380.  
  381.     BEGIN
  382.     {$IFC qDebug}
  383.     ProgramBreak('You must override TMenu.Highlight.');
  384.     {$ENDC}
  385.     END;
  386.  
  387. {--------------------------------------------------------------------------------------------------}
  388. {$S AFields}
  389.  
  390. PROCEDURE TMenu.Fields(PROCEDURE DoToField(fieldName: Str255;
  391.                                            fieldAddr: Ptr;
  392.                                            fieldType: INTEGER)); OVERRIDE;
  393.  
  394.     BEGIN
  395.     DoToField('fFlashInterval', @fFlashInterval, bLongInt);
  396.     DoToField('fNextFlash', @fNextFlash, bLongInt);
  397.     DoToField('fHighlighted', @fHighlighted, bBoolean);
  398.     DoToField('fMenuHandle', @fMenuHandle, bHandle);
  399.     DoToField('fBorder', @fBorder, bRect);
  400.  
  401.     INHERITED Fields(DoToField);
  402.     END;
  403.  
  404. {--------------------------------------------------------------------------------------------------}
  405. {$S ARes}
  406. FUNCTION TMenu.IsItemEnabled(item:INTEGER): Boolean;
  407.  
  408.     BEGIN
  409.     IsItemEnabled := BTst(fMenuHandle^^.enableFlags, item)
  410.     END;
  411.  
  412. {--------------------------------------------------------------------------------------------------}
  413. {$S ARes}
  414.  
  415. PROCEDURE TMenu.GetMenuColors(theMenu, theItem: INTEGER; VAR theMenuColors: MenuColors);
  416.  
  417.     TYPE
  418.         TypeOfMenuInfo = (aMenuItem, aMenuTitle, aMenuBar, noType);
  419.  
  420.     VAR
  421.         aMCEntryPtr: MCEntryPtr;
  422.         typeOfRequest: TypeOfMenuInfo;
  423.         typeOfEntryFound: TypeOfMenuInfo;
  424.         theEntryMenu, theEntryItem: INTEGER;
  425.  
  426.     BEGIN
  427.     WITH theMenuColors DO
  428.         BEGIN
  429.         IF qNeedsColorQD | gConfiguration.hasColorQD THEN
  430.             BEGIN
  431.             IF theItem <> 0 THEN
  432.                 typeOfRequest := aMenuItem
  433.             ELSE IF theMenu <> 0 THEN
  434.                 typeOfRequest := aMenuTitle
  435.             ELSE
  436.                 typeOfRequest := aMenuBar;
  437.  
  438.             theEntryMenu := theMenu;
  439.             theEntryItem := theItem;
  440.  
  441.             aMCEntryPtr := GetMCEntry(theEntryMenu, theEntryItem);
  442.             IF aMCEntryPtr = NIL THEN { not found, try as title }
  443.                 BEGIN
  444.                 theEntryItem := 0;
  445.                 aMCEntryPtr := GetMCEntry(theEntryMenu, theEntryItem);
  446.                 IF aMCEntryPtr = NIL THEN { not found, try as menubar }
  447.                     BEGIN
  448.                     theEntryMenu := 0;
  449.                     aMCEntryPtr := GetMCEntry(theEntryMenu, theEntryItem);
  450.                     END;
  451.                 END;
  452.  
  453.             IF aMCEntryPtr = NIL THEN
  454.                 typeOfEntryFound := noType
  455.             ELSE
  456.                 BEGIN
  457.                 IF theEntryItem <> 0 THEN
  458.                     typeOfEntryFound := aMenuItem
  459.                 ELSE IF theEntryMenu <> 0 THEN
  460.                     typeOfEntryFound := aMenuTitle
  461.                 ELSE
  462.                     typeOfEntryFound := aMenuBar;
  463.                 END;
  464.  
  465.             CASE typeOfEntryFound OF
  466.                 aMenuItem:
  467.                     WITH aMCEntryPtr^ DO
  468.                         BEGIN
  469.                         itemColor := mctRGB1;
  470.                         backgroundColor := mctRGB4;
  471.                         markColor := mctRGB1;
  472.                         commandColor := mctRGB1;
  473.                         END;
  474.                 aMenuTitle:
  475.                     CASE typeOfRequest OF
  476.                         aMenuItem:
  477.                             WITH aMCEntryPtr^ DO
  478.                                 BEGIN
  479.                                 itemColor := mctRGB3;
  480.                                 backgroundColor := mctRGB4;
  481.                                 markColor := mctRGB3;
  482.                                 commandColor := mctRGB3;
  483.                                 END;
  484.                         aMenuTitle:
  485.                             WITH aMCEntryPtr^ DO
  486.                                 BEGIN
  487.                                 itemColor := mctRGB1;
  488.                                 backgroundColor := mctRGB2;
  489.                                 markColor := mctRGB1;
  490.                                 commandColor := mctRGB1;
  491.                                 END;
  492.                     END;
  493.                 aMenuBar:
  494.                     CASE typeOfRequest OF
  495.                         aMenuItem:
  496.                             WITH aMCEntryPtr^ DO
  497.                                 BEGIN
  498.                                 itemColor := mctRGB3;
  499.                                 backgroundColor := mctRGB2;
  500.                                 markColor := mctRGB3;
  501.                                 commandColor := mctRGB3;
  502.                                 END;
  503.                         aMenuTitle:
  504.                             WITH aMCEntryPtr^ DO
  505.                                 BEGIN
  506.                                 itemColor := mctRGB1;
  507.                                 backgroundColor := mctRGB4;
  508.                                 markColor := mctRGB1;
  509.                                 commandColor := mctRGB1;
  510.                                 END;
  511.                         aMenuBar:
  512.                             WITH aMCEntryPtr^ DO
  513.                                 BEGIN
  514.                                 itemColor := mctRGB1;
  515.                                 backgroundColor := mctRGB4;
  516.                                 markColor := mctRGB1;
  517.                                 commandColor := mctRGB1;
  518.                                 END;
  519.                     END;
  520.                 noType:
  521.                     BEGIN
  522.                     itemColor := gRGBBlack;
  523.                     backgroundColor := gRGBWhite;
  524.                     markColor := gRGBBlack;
  525.                     commandColor := gRGBBlack;
  526.                     END;
  527.             END;
  528.             END
  529.         ELSE
  530.             BEGIN
  531.             itemColor := gRGBBlack;
  532.             backgroundColor := gRGBWhite;
  533.             markColor := gRGBBlack;
  534.             commandColor := gRGBBlack;
  535.             END;
  536.         END;
  537.     END;
  538.  
  539. {--------------------------------------------------------------------------------------------------}
  540. {$S ARes}
  541.  
  542. PROCEDURE TMenu.UpdateHighlight(oldItem, newItem: INTEGER);
  543.  
  544.     BEGIN
  545.     { Update highlighting }
  546.     IF newItem <> oldItem THEN
  547.         BEGIN
  548.         IF fHighlighted THEN
  549.             IF oldItem <> kNoMenuItem THEN
  550.                 Highlight(oldItem, false);
  551.  
  552.         fHighlighted := newItem <> kNoMenuItem;
  553.         IF fHighlighted THEN
  554.             Highlight(newItem, TRUE);
  555.  
  556.         IF fFlashInterval >= 0 THEN
  557.             fNextFlash := Future(fFlashInterval);
  558.         END
  559.  
  560.     ELSE IF fFlashInterval >= 0 THEN
  561.         IF TickCount > fNextFlash THEN
  562.             BEGIN
  563.             fHighlighted := NOT fHighlighted;
  564.             Highlight(oldItem, fHighlighted);
  565.             fNextFlash := Future(fFlashInterval);
  566.             END;
  567.     END;
  568.  
  569. {--------------------------------------------------------------------------------------------------}
  570. {$S ARes}
  571.  
  572. FUNCTION TMenu.Focus: BOOLEAN; OVERRIDE;
  573.  
  574.     VAR
  575.         r:                    Rect;
  576.         vorigin:            VPoint;
  577.         origin:             Point;
  578.         {$IFC qDebug}
  579.         currentPort:        GrafPtr;
  580.         {$ENDC}
  581.         theMenuColors:        MenuColors;
  582.  
  583.     BEGIN
  584.     IF IsFocused THEN
  585.         BEGIN
  586.         {$IFC FALSE}
  587.         IF LONGINT(pMenuCPort.portRect.topLeft) <> 0 THEN
  588.             ProgramBreak('TMenu.Focus: Origin is not (0,0)');
  589.  
  590.         GetPort(currentPort);
  591.         IF currentPort <> @pMenuCPort THEN
  592.             ProgramBreak('TMenu.Focus: Port is incorrect');
  593.         {$ENDC}
  594.         END
  595.     ELSE                                                {IF @pMenuCPort <> NIL THEN}
  596.         BEGIN
  597.         IF qNeedsColorQD | gConfiguration.hasColorQD THEN
  598.             InitCPort(@pMenuCPort)
  599.         ELSE
  600.             InitPort(GrafPtr(@pMenuCPort));             { set the port to default settings }
  601.  
  602.         SetPort(@pMenuCPort);
  603.         gLongOffset := gZeroVPt;
  604.  
  605.  
  606.  
  607.         { Try to make the best match for the menu colors without requiring programmer intervention.
  608.         by setting the color environment to be for items. }
  609.  
  610.         GetMenuColors(fMenuHandle^^.menuID, 1, theMenuColors);
  611.         SetIfColor(theMenuColors.itemColor);
  612.         SetIfBkColor(theMenuColors.backgroundColor);
  613.  
  614.         { Change the origin so that drawing is relative to fLocation }
  615.         {$Push}{$H-}
  616.         origin := VPtToPt(fLocation);
  617.         {$Pop}
  618.  
  619.         SubPt(fMenuRect.topLeft, origin);
  620.         SetOrigin(origin.h, origin.v);
  621.  
  622.         {$Push}{$H-}
  623.         AddPt(origin, fHitPt);
  624.         OffsetRect(fMenuRect, origin.h, origin.v);
  625.         ClipRect(fMenuRect);
  626.         {$Pop}
  627.         gFocusedView := SELF;
  628.         END;
  629.     Focus := TRUE;
  630.     END;
  631.  
  632. {--------------------------------------------------------------------------------------------------}
  633. {$S ARes}
  634.  
  635. FUNCTION TMenu.FocusOnSuperView: BOOLEAN; OVERRIDE;
  636.  
  637.     BEGIN
  638.     FocusOnSuperView := false;
  639.     END;
  640.  
  641. {--------------------------------------------------------------------------------------------------}
  642. {$S ARes}
  643.  
  644. FUNCTION TMenu.GetGrafPort: GrafPtr; OVERRIDE;
  645.  
  646.     BEGIN
  647.     GetGrafPort := GrafPtr(@pMenuCPort);
  648.     END;
  649.